#include "TcpConnection.h"
#include "block_log.h"
#include "MessageCodec.h"
#include "protocol.h"
#include "LoginTask.h"
#include "GetFriendListTask.h"
#include "FileUploadTask.h"
#include "FileUploadDataTask.h"
#include "ChatMessageTask.h"
#include "ConnectPool.h"
#include "Connect.h"
#include "ConnectionManager.h"
#include <cstring>
#include <chrono>

int TcpConnection::processRead(void *arg)
{
    TcpConnection *conn = static_cast<TcpConnection *>(arg);
    int socket = conn->m_channel->getSocket();

    int count = conn->m_readBuf->socketRead(socket);
    if (count <= 0)
    {
        conn->m_evLoop->addTask(conn->m_channel, ElemType::DELETE);
        return 0;
    }

    // ✅ 更新定时器（连接有活动）
    conn->setTimerState(TimerState::TIMER_ACTIVE);
    conn->m_evLoop->updateTimer(conn);

    Debug("接收到数据，长度: %d 字节", conn->m_readBuf->readableSize());

    // 处理接收到的数据，可能包含多个完整消息
    while (conn->m_readBuf->readableSize() >= 6) // 至少需要6字节的消息头
    {
        // 步骤 1: 解析消息头（不移动读指针）
        const uint8_t* headerData = reinterpret_cast<const uint8_t*>(conn->m_readBuf->data());
        
        
        auto headerOpt = MessageCodec::parseHeader(headerData, conn->m_readBuf->readableSize());
        
        if (!headerOpt) {
            Debug("消息头解析失败");
            break;
        }
        
        MessageHeader header = *headerOpt;
        Debug("解析消息 - 类型: %u, JSON体长度: %u", header.type, header.length);
        
        // 安全检查：消息类型必须有效
        if (header.type < 1000 || header.type > 6000) {
            Debug("错误：消息类型无效 (%u)，可能是数据损坏", header.type);
            Debug("缓冲区前16字节内容：");
            const uint8_t* buf = reinterpret_cast<const uint8_t*>(conn->m_readBuf->data());
            for (int i = 0; i < 16 && i < conn->m_readBuf->readableSize(); i++) {
                printf("%02x ", buf[i]);
            }
            printf("\n");
            
            // 逐字节扫描，寻找下一个有效消息头
            Debug("尝试恢复同步...");
            bool found = false;
            for (int skip = 1; skip < conn->m_readBuf->readableSize() - 6; skip++) {
                const uint8_t* test_buf = reinterpret_cast<const uint8_t*>(conn->m_readBuf->data()) + skip;
                auto test_header = MessageCodec::parseHeader(test_buf, conn->m_readBuf->readableSize() - skip);
                if (test_header && test_header->type >= 1000 && test_header->type <= 6000 
                    && test_header->length < 20 * 1024 * 1024) {
                    Debug("找到可能的消息头，跳过 %d 字节", skip);
                    conn->m_readBuf->readPosIncrease(skip);
                    found = true;
                    break;
                }
            }
            
            if (!found) {
                Debug("无法恢复，清空缓冲区");
                conn->m_readBuf->readPosIncrease(conn->m_readBuf->readableSize());
            }
            break;
        }
        
        // 安全检查：消息长度不能超过 20MB
        const uint32_t MAX_MESSAGE_LENGTH = 20 * 1024 * 1024;
        if (header.length > MAX_MESSAGE_LENGTH) {
            Debug("错误：消息长度异常 (%u 字节)，超过最大限制 (%u 字节)，可能是数据损坏", 
                  header.length, MAX_MESSAGE_LENGTH);
            Debug("缓冲区前16字节内容：");
            const uint8_t* buf = reinterpret_cast<const uint8_t*>(conn->m_readBuf->data());
            for (int i = 0; i < 16 && i < conn->m_readBuf->readableSize(); i++) {
                printf("%02x ", buf[i]);
            }
            printf("\n");
            
            // 清空缓冲区，防止错误累积
            conn->m_readBuf->readPosIncrease(conn->m_readBuf->readableSize());
            Debug("已清空读缓冲区");
            break;
        }
        
        // 步骤 2: 检查是否接收到完整消息
        // 完整消息长度 = 消息头(6字节) + JSON体长度
        uint32_t totalLength = 6 + header.length;
        if (conn->m_readBuf->readableSize() < totalLength) {
            Debug("消息不完整，等待更多数据。需要: %u, 当前: %d", 
                  totalLength, conn->m_readBuf->readableSize());
            break; // 等待更多数据
        }
        
        // 步骤 3: 提取完整消息（包括消息头 6 字节 + JSON 体）
        std::vector<uint8_t> messageData(totalLength);
        std::memcpy(messageData.data(), conn->m_readBuf->data(), totalLength);
        
        // 步骤 4: 移动读指针
        conn->m_readBuf->readPosIncrease(totalLength);
        
        // 步骤 5: 解码消息
        auto [msgType, jsonBody] = MessageCodec::decode(messageData);
        Debug("收到消息类型: %u, JSON 长度: %zu", static_cast<uint16_t>(msgType), jsonBody.length());
        
        // 步骤 6: 根据消息类型创建并提交任务
        switch (msgType) {
            case MsgType::LOGIN_REQ:
            {
                Debug("处理登录请求");
                // 创建登录任务并提交到业务线程池
                auto loginTask = std::make_shared<LoginTask>(conn, jsonBody);
                WorkerThreadPool::getInstance()->submitTask(
                    [loginTask]() { loginTask->work(nullptr); }
                );
                break;
            }
            case MsgType::FILE_UPLOAD_REQ:
            {
                auto task=std::make_shared<FileUploadTask>(conn, jsonBody);
                WorkerThreadPool::getInstance()->submitTask(
                    [task]() { task->work(nullptr); }
                );
                break;
            }

            case MsgType::FILE_UPLOAD_DATA:
            {
                auto task=std::make_shared<FileUploadDataTask>(conn, jsonBody);
                WorkerThreadPool::getInstance()->submitTask(
                    [task]() { task->work(nullptr); }
                );
                break;
            }
            
            case MsgType::GET_FRIEND_LIST_REQ:
            {
                Debug("处理获取好友列表请求");
                // 创建获取好友列表任务并提交到业务线程池
                auto getFriendListTask = std::make_shared<GetFriendListTask>(conn, jsonBody);
                WorkerThreadPool::getInstance()->submitTask(
                    [getFriendListTask]() { getFriendListTask->work(nullptr); }
                );
                break;
            }
            
            case MsgType::HEARTBEAT:
            {
                Debug("收到心跳消息");
                // TODO: 处理心跳（可以直接响应，不需要业务线程）
                break;
            }
            
            case MsgType::TEXT_MSG:
            {
                Debug("收到文本消息");
                auto chatTask = std::make_shared<ChatMessageTask>(conn, jsonBody);
                WorkerThreadPool::getInstance()->submitTask(
                    [chatTask]() { chatTask->work(nullptr); }
                );
                break;
            }
            
            default:
            {
                Debug("未知消息类型: %u", static_cast<uint16_t>(msgType));
                break;
            }
        }
    }

    return 0;
}

int TcpConnection::processWrite(void *arg)
{
    Debug("开始发送数据了(基于写事件发送)....");
    TcpConnection *conn = static_cast<TcpConnection *>(arg);
    // 发送数据

    int count = conn->m_writeBuf->sendData(conn->m_channel->getSocket());

    // ✅ 更新定时器（连接有活动）
    conn->setTimerState(TimerState::TIMER_ACTIVE);
    conn->m_evLoop->updateTimer(conn);
    
    if (count > 0)
    {
        // 判断数据是否被全部发送出去了
        if (conn->m_writeBuf->readableSize() == 0)
        {
            // 1. 不再检测写事件 -- 修改channel中保存的事件
            conn->m_channel->writeEventEnable(false);
            // 2. 修改dispatcher检测的集合 -- 添加任务节点
            conn->m_evLoop->addTask(conn->m_channel, ElemType::MODIFY);

            // 这里我们是长连接所以不删除这个节点
            //  // 3. 删除这个节点
            //  conn->m_evLoop->addTask(conn->m_channel, ElemType::DELETE);
        }
    }
    return 0;
}

int TcpConnection::destroy(void *arg)
{
    TcpConnection *conn = static_cast<TcpConnection *>(arg);
    if (conn != nullptr)
    {
        delete conn;
    }
    return 0;
}

TcpConnection::TcpConnection(int fd, EventLoop *evloop)
{
    m_evLoop = evloop;
    m_readBuf = new Buffer(10240);
    m_writeBuf = new Buffer(10240);
    m_name = "Connection-" + to_string(fd);
    m_channel = new Channel(fd, FDEvent::ReadEvent, processRead, processWrite, destroy, this);
    evloop->addTask(m_channel, ElemType::ADD);

    m_evLoop->addTimer(this);

    Debug("有新连接到来:fd %d", fd);
    LOG_DEBUG("有新客户端连接：%d", fd);
}

TcpConnection::~TcpConnection()
{
    // 1. 如果用户已登录，记录下线信息并更新数据库
    if (m_isLoggedIn) {
        Debug("用户 %lu 下线，连接断开", m_userId);
        logout();  // 更新数据库状态为离线
    }

    // 2. 安全移除定时器
    if (m_evLoop) {
        m_evLoop->removeTimer(this);
    }

    // 3. 释放读写缓冲区（无条件释放）
    delete m_readBuf;
    delete m_writeBuf;
    m_readBuf = nullptr;
    m_writeBuf = nullptr;

    // 4. 安全释放通道
    if (m_channel && m_evLoop) {
        // 先确保从事件循环中移除
        //  m_evLoop->addTask(m_channel, ElemType::DELETE);
        // 然后释放资源
        m_evLoop->freeChannel(m_channel);
        m_channel = nullptr;
    }

    Debug("连接断开, 释放资源, gameover, connName: %s", m_name.c_str());
}

// 用户登出（更新数据库状态为离线，并通知好友）
void TcpConnection::logout()
{
    if (!m_isLoggedIn || m_userId == 0) {
        return;  // 未登录，无需处理
    }
    
    uint64_t currentUserId = m_userId;  // 保存用户ID，后面需要用
    
    try {
        // 获取数据库连接
        auto connPool = ConnectionPool::getConnectionPool();
        auto dbConn = connPool->getConnection();
        
        if (!dbConn) {
            Debug("获取数据库连接失败，无法更新用户离线状态");
            m_userId = 0;
            m_isLoggedIn = false;
            return;
        }
        
        sql::Connection* conn = dbConn->getConnection();
        
        // 步骤1: 更新用户状态为离线（status = 0）
        std::unique_ptr<sql::PreparedStatement> updateStmt(
            conn->prepareStatement(
                "UPDATE users SET status = 0 WHERE user_id = ?"
            )
        );
        
        updateStmt->setUInt64(1, currentUserId);
        int rows = updateStmt->executeUpdate();
        
        if (rows > 0) {
            Debug("用户 %lu 状态已更新为离线", currentUserId);
        } else {
            Debug("警告：用户 %lu 状态更新失败（用户可能不存在）", currentUserId);
        }
        
        // 步骤2: 查询该用户的所有好友
        std::unique_ptr<sql::PreparedStatement> queryStmt(
            conn->prepareStatement(
                "SELECT friend_id FROM friendships WHERE user_id = ?"
            )
        );
        queryStmt->setUInt64(1, currentUserId);
        std::unique_ptr<sql::ResultSet> res(queryStmt->executeQuery());
        
        std::vector<uint64_t> friendIds;
        while (res->next()) {
            uint64_t friendId = res->getUInt64("friend_id");
            friendIds.push_back(friendId);
        }
        
        Debug("用户 %lu 有 %zu 个好友需要通知", currentUserId, friendIds.size());
        
        // 步骤3: 构造好友状态通知消息
        FriendStatusNotify notify;
        notify.user_id = currentUserId;
        notify.status = 0;  // 离线
        notify.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::system_clock::now().time_since_epoch()
        ).count();
        
        auto notifyData = MessageCodec::encode(notify);
        
        // 步骤4: 给在线的好友推送状态更新
        int notifyCount = 0;
        for (uint64_t friendId : friendIds) {
            TcpConnection* friendConn = ConnectionManager::getInstance()->getConnection(friendId);
            if (friendConn) {
                friendConn->sendResponseAsync(notifyData);
                notifyCount++;
                Debug("已通知好友 %lu：用户 %lu 已离线", friendId, currentUserId);
            }
        }
        
        Debug("成功通知 %d 个在线好友", notifyCount);
        
    } catch (const sql::SQLException& e) {
        Debug("数据库操作异常: %s (错误码: %d)", e.what(), e.getErrorCode());
    }
    
    // 步骤5: 从全局连接管理器中注销
    ConnectionManager::getInstance()->unregisterConnection(currentUserId);
    
    // 步骤6: 清空内存中的登录状态
    m_userId = 0;
    m_isLoggedIn = false;
}

// 异步发送响应数据（线程安全）
void TcpConnection::sendResponseAsync(const std::vector<uint8_t>& data)
{
    if (data.empty()) {
        return;
    }
    
    // 将数据写入发送缓冲区
    m_writeBuf->appendString(reinterpret_cast<const char*>(data.data()), data.size());
    
    // 启用写事件检测
    m_channel->writeEventEnable(true);
    
    // 通知事件循环修改事件
    m_evLoop->addTask(m_channel, ElemType::MODIFY);
}